//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "ccondition.h"
#include "cmutex.h"
#include "pseudo.h"
#include "cthread.h"
#include "helper.h"
#include <aura.h>
#include <elacs.h>

CCondition::~CCondition()
{
    if (NULL != m_hCondition) {
        AuraCondition_Destroy(m_hCondition);
        m_hCondition = NULL;
    }
}

ECode CCondition::Initialize()
{
    return AuraCondition_Create(&m_hCondition);
}

PInterface CCondition::Probe(
    /* [in ] */ REIID riid)
{
    if (riid == EIID_IInterface) {
        return (PInterface)(ICondition *)this;
    }
    else if (riid == EIID_ICondition) {
        return (ICondition *)this;
    }
    else if (riid == EIID_CLASS_INFO) {
        return (PInterface)&ECLSID_CCondition;
    }
    else if (riid == EIID_INTERFACE_INFO) {
        return (PInterface)&EIID_ICondition;
    }

    return NULL;
}

UInt32 CCondition::AddRef()
{
    Int32 nRef = m_cRef.Increment();
    return (UInt32)nRef;
}

UInt32 CCondition::Release()
{
    Int32 nRef = m_cRef.Decrement();
    if (0 >= nRef) {
        delete this;
    }
    return (UInt32)nRef;
}

ECode CCondition::Aggregate(
    /* [in ] */ AggregateType type,
    /* [out] */ PInterface pObject)
{
    return E_NOT_IMPLEMENTED;
}

ECode CCondition::GetDomain(
    /* [out] */ PInterface * ppObject)
{
    return E_NOT_IMPLEMENTED;
}

ECode CCondition::Wait(
    /* [in] */ IMutex *pMutex,
    /* [out] */ WaitResult *pResult)
{
    if ((NULL == pMutex)
        || (NULL == pResult)) {
        return E_INVALID_ARGUMENT;
    }

    return this->TryWait(pMutex, INFINITE, pResult);
}

ECode CCondition::TryWait(
    /* [in] */ IMutex *pMutex,
    /* [in] */ Millisecond32 msTimeout,
    /* [out] */ WaitResult *pResult)
{
    Aura_Handle hMutex = NULL;
    ECode ec = NOERROR;

    if ((NULL == pMutex)
        || (NULL == pResult)
        || ((msTimeout <= 0) && (INFINITE != msTimeout))) {
        return E_INVALID_ARGUMENT;
    }

    hMutex = (static_cast<CMutex *>(pMutex))->GetHandle();
    THREAD_START_SLEEP()
    {
        ec = AuraCondition_Wait(m_hCondition,
                             hMutex,
                             msTimeout,
                            (Aura_WaitResult *)pResult);
    }
    THREAD_END_SLEEP;

    return ec;
}

ECode CCondition::Pulse()
{
    return AuraCondition_Pulse(m_hCondition);
}

ECode CCondition::PulseAll()
{
    return AuraCondition_PulseAll(m_hCondition);
}

ECode CCondition::S_Create(
    /* [out] */ ICondition ** ppCondition)
{
    CCondition * pCondition = NULL;
    ECode ec = NOERROR;

    assert(NULL != ppCondition);

    pCondition = new CCondition();
    if (NULL == pCondition) {
        ec = E_OUT_OF_MEMORY;
        goto ErrorExit;
    }
    ec = pCondition->Initialize();
    if (FAILED(ec)) {
        goto ErrorExit;
    }
    pCondition->AddRef();

    *ppCondition = static_cast<ICondition *>(pCondition);
    return NOERROR;

ErrorExit:
    if (NULL != pCondition) {
        delete pCondition;
    }
    return ec;
}

